<?php
/**
 * Created by PhpStorm.
 * User: baiyunfei
 * Date: 2018/10/30
 * Time: 3:51 PM
 */
namespace whisper;

use dingdong\service\EventTrait;
use Inhere\Console\IO\Output;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;

class WebSocket
{
    use EventTrait;

    private $config = [];

    protected $onlineUsers = [];

    protected $onlineKeFu = [];

    protected $userIdFdMap = [];

    protected $nowClientIp = [];

    private $output;

    private $log;

    public $db;

    /**
     * 运行服务器
     */
    public function run(): void
    {
        $this->checkSapiEnv();
        $this->start();
    }

    public function setting(array $config = []): void
    {
        $this->config = $config;

        $this->output = new Output();

        $this->log = new Logger('whisper_log');
        $this->log->pushHandler(new StreamHandler($this->config['server']['log_file']));
    }

    /**
     * 检测环境
     */
    protected function checkSapiEnv(): void
    {
        if (php_sapi_name() != "cli") {
            exit("only run in command line mode " . PHP_EOL);
        }
    }

    /**
     * 运行服务
     */
    private function start(): void
    {
        date_default_timezone_set('Asia/Shanghai');
        \Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);
        \Co\Run(function () {

            $this->db = new PDOPool((new PDOConfig)
                ->withHost($this->config['db']['host'])
                ->withPort($this->config['db']['port'])
                // ->withUnixSocket('/tmp/mysql.sock')
                ->withDbName($this->config['db']['database'])
                ->withCharset($this->config['db']['charset'])
                ->withUsername($this->config['db']['user'])
                ->withPassword($this->config['db']['password']));

            $config = $this->config;
            $server = new \Swoole\Coroutine\Http\Server("0.0.0.0", $config['port']);

            $server->handle('/', function ($req, $ws) {
                $sessionId = $req->fd;
                $this->nowClientIp = isset($req->header['x-real-ip']) ? $req->header['x-real-ip'] : '127.0.0.1';

                // websocket 模式
                if (strstr($req->server['request_uri'], '/websocket') !== false) {
                    $ws->fd = $sessionId;
                    // websocket 模式
                    $ws->upgrade();

                    while (true) {
                        $frame = $ws->recv();
                        if ($frame === false) {

                            break;
                        } else if ($frame == '') {

                            break;
                        } else {

                            $this->onMessage($sessionId, $frame->data, $ws);
                        }
                    }

                    $this->onExit($sessionId);
                } else {

                    $this->onHttpMessage($req->post, $ws);
                }
            });

            $this->display();
            $server->start();
        });
    }

    /**
     * 展示运行数据
     */
    private function display(): void
    {
        $startTime = date('Y-m-d H:i:s');
        $logo =<<<EOL
      _ _                 _                   
     | (_)               | |                  
   __| |_ _ __   __ _  __| | ___  _ __   __ _ 
  / _` | | '_ \ / _` |/ _` |/ _ \| '_ \ / _` |
 | (_| | | | | | (_| | (_| | (_) | | | | (_| |
  \__,_|_|_| |_|\__, |\__,_|\___/|_| |_|\__, |
                 __/ |                   __/ |
                |___/                   |___/ 
EOL;
        $this->output->writeln($logo);
        $this->output->writeln('');
        $this->output->writeln('-----------------------<info> whisper </info>-----------------------');
        $this->output->writeln('whisper server version: ' . $this->config['version'] . '   php version: ' . PHP_VERSION);
        $this->output->writeln('-----------------------<info>  info   </info>-----------------------');
        $this->output->writeln('listen                    worker            status');
        $this->output->writeln('websocket://0.0.0.0:' . $this->config['port'] . '    ' . $this->config['server']['worker_num'] . '                 <info>ok</info>');
        $this->output->writeln('http://127.0.0.1:' . $this->config['port'] . '       ' . $this->config['server']['worker_num'] . '                 <info>ok</info>');
        $this->output->writeln('-------------------------------------------------------');
        $this->output->writeln('');
        $this->output->writeln('start at：' . $startTime);
        $this->output->writeln('');
        $this->output->writeln('Press Ctrl+C to stop. Start success.');
    }
}